package net.sf.fc.io;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * Class that encapsulates a List of FileList objects. The FileLists object is used to represent all source files and all destination files.
 * Each FileList object represents a file or list of files and an Options object that represents the copy options to use when copying. The
 * Options object can be null. If it is null, the Options object is used elsewhere. If the file is a source file, the Options object that
 * gets used is the default options object defined when the FileCopier object is instantiated. If the file is a destination file and its
 * Options object is null, the Options object used is the source file's Options object unless that, too, is null. If the source object's
 * Options object is null, it uses the default options object defined when the FileCopier object is instantiated.
 * In a FileLists object, each FileList object represents a file or list of files that share a common Options object. If all source files
 * or destination files will share the same Options object, the File objects should all be in one FileList object. So, the FileLists object
 * would only have one FileList object.
 * @author david
 *
 */
public final class FileLists implements Iterable<FileList> {

    private final List<FileList> fileLists;
    private final List<FileList> unmodifiableFileLists;

    private volatile int hashCode = 0;

    public FileLists(List<FileList> fileLists) {
        this.fileLists = new ArrayList<>(fileLists);
        unmodifiableFileLists = Collections.unmodifiableList(this.fileLists);
    }

    /**
     * Convenience constructor that takes a variable number of FileList objects and puts them in a List.
     * @param fileLists
     */
    public FileLists(FileList ...fileLists) {
        this(Arrays.asList(fileLists));
    }

    /**
     * Convenience constructor that takes an Options object and a variable number of File objects. These are used to construct a
     * FileList object. The FileLists object will have one FileList object in it.
     * @param options
     * @param files
     */
    public FileLists(Options options, File ...files) {
        this(new FileList(options, files));
    }

    /**
     * Convenience constructor that takes a List of File objects. These are used to construct a FileList object with
     * a null Options object. The FileLists object will have one FileList object in it.
     * @param files
     */
    public FileLists(File ...files) {
        this(null, files);
    }

    /**
     * Convenience constructor that takes an Options object and a List of File objects. These are used to construct a
     * FileList object. The FileLists object will have one FileList object in it.
     * @param options
     * @param files
     */
    public FileLists(Options options, List<File> files) {
        this(new FileList(options, files));
    }

    public List<FileList> getFileLists() {
        return unmodifiableFileLists;
    }

    @Override
    public boolean equals(Object object) {
        if(!(object instanceof FileLists)) return false;
        if(object == this) return true;

        FileLists that = (FileLists)object;

        return this.fileLists.equals(that.fileLists);
    }

    @Override
    public int hashCode() {
        if(hashCode == 0) {
            int result = 17;
            result = 37*result+fileLists.hashCode();
            hashCode = result;
        }
        return hashCode;
    }

    @Override
    public Iterator<FileList> iterator() {
        return unmodifiableFileLists.iterator();
    }
}
